package com.bluemedia.calculator;

import com.vaadin.Application;
import com.vaadin.ui.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Marek Rucki
 * Date: 14.04.11
 * Time: 10:58
 */
public class CalculatorApplication extends Application implements Button.ClickListener{

    private Computation currentComputation = new Computation();
    private String numberToDisplay = "";

    //The main Layout
    private VerticalLayout layout = new VerticalLayout();

    // 10 buttons (from 0 to 9, each representing a number)
    private List<Button> nbButtonList = new ArrayList<Button>();

    private TextField field = new TextField("Result");

    private Button addButton = new Button("+", this);
    private Button substractButton = new Button("-", this);
    private Button multiplyButton = new Button("*", this);
    private Button divideButton = new Button("/", this);
    private Button equalsButton = new Button("=", this);
    private Button powerButton = new Button("^", this);
    private Button clearButton = new Button("C", this);

    @Override
    public void init() {
        Window mainWindow = new Window("Grid Layout Application");
        setMainWindow(mainWindow);

        mainWindow.addComponent(layout);
    }

    public CalculatorApplication(){

        //The gridLayout for the calculator
        GridLayout grid = new GridLayout(4, 6);
        layout.addComponent(grid);
        grid.setSpacing(true);

        // number buttons creation
        for(int i = 0; i < 10; i++){
            nbButtonList.add(new Button(String.valueOf(i), this));
        }

        // number buttons positionning in the grid
        grid.addComponent(nbButtonList.get(0), 1, 4);
        grid.addComponent(nbButtonList.get(1), 0, 1);
        grid.addComponent(nbButtonList.get(2), 0, 2);
        grid.addComponent(nbButtonList.get(3), 0, 3);
        grid.addComponent(nbButtonList.get(4), 1, 1);
        grid.addComponent(nbButtonList.get(5), 1, 2);
        grid.addComponent(nbButtonList.get(6), 1, 3);
        grid.addComponent(nbButtonList.get(7), 2, 1);
        grid.addComponent(nbButtonList.get(8), 2, 2);
        grid.addComponent(nbButtonList.get(9), 2, 3);


        // All other components
        grid.addComponent(field, 0, 0, 2, 0);  // The field spans multiple cells of the grid.
        grid.addComponent(addButton, 3, 1);
        grid.addComponent(substractButton, 3, 2);
        grid.addComponent(multiplyButton, 3, 3);
        grid.addComponent(divideButton, 3, 4);
        grid.addComponent(equalsButton, 3, 5);
        grid.addComponent(powerButton, 0, 4);
        grid.addComponent(clearButton, 2, 4);
    }

    public void buttonClick(Button.ClickEvent event){

        //If the button is a number
        for(int i = 0; i < 10; i++){
            if (event.getButton() == nbButtonList.get(i)){
                int nb = nbButtonList.indexOf(event.getButton());
                //We display it
                numberToDisplay += String.valueOf(nb);
                field.setValue(numberToDisplay);
                return;
            }
        }

        //If the button is an operation
        if(event.getButton() == addButton){
            prepareOperation(Operation.ADD, "+");
        } else if (event.getButton() == substractButton){
            prepareOperation(Operation.SUBSTRACT, "-");
        } else if (event.getButton() == multiplyButton){
            prepareOperation(Operation.MULTIPLY, "*");
        } else if (event.getButton() == divideButton){
            prepareOperation(Operation.DIVIDE, "/");
        } else if (event.getButton() == powerButton){
            prepareOperation(Operation.POWER, "^");
        } else if(event.getButton() == clearButton){
            numberToDisplay = "";
            currentComputation.number1 = 0.0;
            currentComputation.number2 = 0.0;
            field.setValue("");
        }

        //When press to the equals button
        if (event.getButton() == equalsButton){
            //We remind the second number if it exist
            if (numberToDisplay!= ""){
                currentComputation.number2 = Double.valueOf(numberToDisplay);
            }

            //Check there is a current operation
            if (currentComputation.operation == null) {
                currentComputation.number1 = 0.0;
                return;
            }

            //And check wich operation we must made
            switch(currentComputation.operation){
            case ADD:
                currentComputation.number1 += currentComputation.number2;
                break;
            case SUBSTRACT:
                currentComputation.number1 -= currentComputation.number2;
                break;
            case MULTIPLY:
                currentComputation.number1 *= currentComputation.number2;
                break;
            case DIVIDE:
                currentComputation.number1 /= currentComputation.number2;
                break;
            case POWER:
                currentComputation.number1 = Math.pow(currentComputation.number1, currentComputation.number2);
                break;
            }

            //And display the result
            field.setValue(String.valueOf(currentComputation.number1));
        }
    }

    private void prepareOperation(Operation operation, String opStr) {
        //We remind the operation
        currentComputation.operation = operation;
        //Save the first number
        currentComputation.number1 = Double.valueOf(numberToDisplay);
        //Display the operation
        field.setValue(opStr);
        //And clear textarea for the nex number
        numberToDisplay = "";
    }

    //ENUM for operations
    enum Operation {ADD, SUBSTRACT, DIVIDE, MULTIPLY, POWER}

    //Inner class
    class Computation {
        Double number1;
        Double number2;
        Operation operation;
    }

}
